package com.atguigu.gmall.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Resource
    private RedisTemplate redisTemplate;

    @Value("${authUrls.url}")
    private String[] authUrls;

    @Value("${authUrls.loginUrl}")
    private String loginUrl;

    //全局过滤器执行方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //获取当前的URI
        String path = request.getURI().getPath();
        //内部资源不允许浏览器访问 /**/inner/**
        if (antPathMatcher.match("/**/inner/**",path)){
            return getVoidMono(response,ResultCodeEnum.PERMISSION);
        }
        //异步 判断当前URI是否必须登录 /**/auth/**
        //获取用户ID
        String userId = getUserId(request);
        if (antPathMatcher.match("/**/auth/**",path)){
            //该路径下必须登录 判断用户是否已经登录
            if (StringUtils.isEmpty(userId)){
                return getVoidMono(response,ResultCodeEnum.LOGIN_AUTH);
            }
        }

        //同步 /trade.html /order.html  /pay.html  网关路由到后面页面微服务
        for (String url : authUrls) {
            if (path.contains(url) && StringUtils.isEmpty(userId)){
                //需要登录
                //重定向
                response.setStatusCode(HttpStatus.SEE_OTHER);
                try {
                    response.getHeaders().set(HttpHeaders.LOCATION,loginUrl + URLEncoder.encode(request.getURI().toString(),"utf-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return response.setComplete();
            }
        }
        //加入购物车 向微服务传递用户ID
        if (!StringUtils.isEmpty(userId)) {
            request.mutate().header("userId",userId);
        }
        //向微服务传递临时用户ID
        String userTempId = getUserTempId(request);
        if (!StringUtils.isEmpty(userTempId)){
            request.mutate().header("userTempId",userTempId);
        }
        return chain.filter(exchange);
    }

    private Mono<Void> getVoidMono(ServerHttpResponse response,ResultCodeEnum resultCodeEnum) {
        Result<Object> result = Result.build(null, resultCodeEnum);
        String string = JSONObject.toJSONString(result);
        DataBuffer wrap = response.bufferFactory().wrap(string.getBytes());
        //乱码问题
        response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
        return response.writeWith(Mono.just(wrap));
    }

    //获取临时用户Id
    private String getUserTempId(ServerHttpRequest request){
        //同步 请求头获取
        String userTempId = request.getHeaders().getFirst("userTempId");
        if (StringUtils.isEmpty(userTempId)){
            //异步 cookie中获取
            HttpCookie httpCookie = request.getCookies().getFirst("userTempId");
            if (httpCookie != null){
                userTempId = httpCookie.getValue();
            }
        }
        return userTempId;
    }

    //获取用户Id
    private String getUserId(ServerHttpRequest request) {
        //异步 令牌在请求头中 同步令牌在cookie中
        //获取令牌
        String token = request.getHeaders().getFirst("token");
        if (StringUtils.isEmpty(token)){
            HttpCookie httpCookie = request.getCookies().getFirst("token");
            if (httpCookie != null){
                token = httpCookie.getValue();
            }
        }

        //判断token是否存在
        if (!StringUtils.isEmpty(token)){
            if (redisTemplate.hasKey(token)){
                String userId = (String) redisTemplate.opsForValue().get(token);
                return userId;
            }
        }

        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
